package cn.numeron.wxarticle.api.wxarticle

import androidx.paging.PagingSource
import androidx.paging.PagingState
import androidx.sqlite.db.SimpleSQLiteQuery
import cn.numeron.common.json.Page
import cn.numeron.wxarticle.api.other.WxArticleApi
import javax.inject.Inject

class WxArticleRepository @Inject constructor() {

    @Inject
    lateinit var wxArticleDao: WxArticleDao

    @Inject
    lateinit var wxArticleApi: WxArticleApi

    fun pagingSource(parameter: WxArticleParameter): PagingSource<WxArticleParameter, WxArticle> {
        return object : PagingSource<WxArticleParameter, WxArticle>() {

            private var pageSize = 20
            private var pageCount = Int.MAX_VALUE

            override fun getRefreshKey(state: PagingState<WxArticleParameter, WxArticle>): WxArticleParameter {
                return parameter.copy(pageIndex = 1)
            }

            override suspend fun load(params: LoadParams<WxArticleParameter>): LoadResult<WxArticleParameter, WxArticle> {
                return try {
                    val wxArticleParameter = params.key!!
                    val keyword = wxArticleParameter.keyword
                    val pageIndex = wxArticleParameter.pageIndex
                    val pageData = try {
                        //默认从网络加载数据
                        //从网络获取这一页的数据
                        val pageData = loadPage(pageIndex, keyword)
                        pageCount = pageData.pageCount
                        pageSize = pageData.size
                        //保存到本地数据库中
                        wxArticleDao.save(pageData.data)
                        //计算上一页和下一页的索引
                        pageData.data
                    } catch (throwable: Exception) {
                        //从网络加载数据失败后，从本地加载缓存的数据
                        //计算要忽略多少条数据
                        val offset = (pageIndex - 1) * pageSize
                        //获取这一页的数据
                        val segmentList = findByKeyword(keyword, PAGE_SIZE, offset)
                        if (segmentList.isEmpty()) {
                            //如果本地没有数据，则抛出异常
                            return LoadResult.Error(throwable)
                        }
                        segmentList
                    }
                    val prevKey =
                        if (pageIndex > 1) wxArticleParameter.copy(pageIndex = pageIndex - 1) else null
                    val nextKey =
                        if (pageIndex < pageCount) wxArticleParameter.copy(pageIndex = pageIndex + 1) else null
                    LoadResult.Page(pageData, prevKey, nextKey)
                } catch (throwable: Throwable) {
                    LoadResult.Error(throwable)
                }
            }

        }
    }

    private suspend fun findByKeyword(keyword: String?, limit: Int, offset: Int): List<WxArticle> {
        var sql = "SELECT * FROM wx_article"
        if (!keyword.isNullOrEmpty()) {
            sql += " WHERE title LIKE '%${keyword}%'"
        }
        sql += " ORDER BY share_time DESC LIMIT $limit OFFSET $offset"
        return wxArticleDao.findByKeyword(SimpleSQLiteQuery(sql))
    }

    private suspend fun loadPage(pageIndex: Int, keyword: String? = null): Page<WxArticle> {
        return wxArticleApi.getWxArticleList(pageIndex, keyword).data
    }

    companion object {

        const val PAGE_SIZE = 20

    }

}